using Chaotic.DataBase.DataAccess;
using Chaotic.DataBase.DBAccessLibrary.DBAccessLibrary;
using Chaotic.DataBase.DBAccessLibrary.Interface;
using Chaotic.DataBase.DBAccessLibrary.Model;

namespace Chaotic.DataBase.DBAccessLibrary.Grammar;

internal class OracleGrammar : DBGrammar, IGrammar, ILocalGrammar
{
	public string GetChTableSql
	{
		get
		{
			if (string.IsNullOrEmpty(_xml.ChDescription))
			{
				return "SELECT TABLENAME,CHINESETABLENAME as CHINATABLENAME,FIELDNAME as COLUMNNAME,CHINESENAME as CHINACOLUMNNAME FROM T_FIELD_DICTIONARY order by TABLENAME";
			}
			return _xml.ChDescription;
		}
	}

	public string? IsExistChTableSql => "select table_name from user_tables where table_name='T_FIELD_DICTIONARY'";

	public OracleGrammar(ConnectionModel? connect)
		: base(connect)
	{
	}

	private string? GetTypeFilter(FieldEntity? field, string sql)
	{
		string? text = field.TypeName;
		int.TryParse(field.Length, out var _);
		string? text2 = field.Length;
		string text3 = field.TypeName.ToUpper();
		if (text3 == "VARCHAR2" || text3 == "VARCHAR")
		{
			text = "VARCHAR2";
			text2 = "(" + field.Length + ")";
		}
		if (text3 == "INTEGER" || text3 == "SMALLINT")
		{
			text2 = "";
		}
		if (text3 == "NUMBER")
		{
			text2 = "(" + field.Length + ")";
		}
		if (text3 == "TIMESTAMP" || text3 == "DATE")
		{
			text2 = "";
		}
		return string.Format(sql, field.TableName, field.Name, text, text2);
	}

	public string? AddColumn(FieldEntity? field)
	{
		string text = "ALTER TABLE {0} ADD {1} {2}{3}";
		if (!field.IsNull)
		{
			text += " Not Null";
		}
		if (!string.IsNullOrEmpty(field.DefaultValue))
		{
			text = text + " DEFAULT " + field.DefaultValue;
		}
		return GetTypeFilter(field, text);
	}

	public IEnumerable<string?> EditColumn(FieldEntity? field)
	{
		List<string?> list = new List<string?>();
		string text = "ALTER TABLE {0} MODIFY {1} {2}{3}";
		if (field.IsChange((FieldEntity o) => o.IsNull))
		{
			text = ((!field.IsNull) ? (text + " Not Null") : (text + " Null"));
		}
		list.Add(GetTypeFilter(field, text));
		string.IsNullOrEmpty(field.DefaultValue);
		return list;
	}

	public IEnumerable<string?> RemoveColumn(FieldEntity field)
	{
		List<string?> list = new List<string?>();
		list.Add($"ALTER TABLE {field.TableName} DROP COLUMN {field.TransName}");
		return list;
	}

	public IEnumerable<string?> EditPrimary(TableEntity table)
	{
		List<string?> list = new List<string?>();
		string text = table.PrimaryKeyName;
		string[] array = (from o in table.FileNodes
			where o.IsPrimaryKey
			select o.Name).ToArray();
		if (array.Length > 0)
		{
			if (!string.IsNullOrEmpty(text))
			{
				string? item = $"alter table {table.Name} drop constraint {text} cascade";
				list.Add(item);
			}
			else
			{
				text = "PK" + array[0];
			}
			list.Add(string.Format("ALTER TABLE {0} ADD CONSTRAINT {1} PRIMARY KEY({2})", table.Name, text, string.Join(",", array)));
		}
		return list;
	}

	public string? SelectTop(TableEntity table, int count)
	{
		string format = "SELECT * FROM {0} WHERE ROWNUM <= {1}";
		return string.Format(format, table.TransName, count);
	}

	public string AppendTabText(string text)
	{
		return TabText(text);
	}

	public string GetErrorInfo(string errorMsg)
	{
		return string.Empty;
	}

	public string? GetProcParamInfo(ProcEntity entity)
	{
		if (entity == null)
		{
			return string.Empty;
		}
		string arg;
		if (entity.ChildNodes.Count > 0)
		{
			List<string> list = new List<string>();
			foreach (ProcParamEntity? childNode in entity.ChildNodes)
			{
				if (childNode.Status == "IN")
				{
					list.Add($"{Environment.NewLine}[{childNode.Name}({childNode.TypeName})]");
				}
				else
				{
					list.Add($"{Environment.NewLine}[{childNode.Name}({childNode.TypeName})-OUT]");
				}
			}
			arg = "(" + string.Join(",", list.ToArray()) + ")";
		}
		else
		{
			arg = "()";
		}
		return $"{"EXEC"} {entity.Name}{arg}";
	}

	public string GetPageingSql(string sql, decimal index, decimal count)
	{
		string format = "SELECT tab.* FROM (SELECT {0} ROWNUMBER,t.* FROM (" + Environment.NewLine + "{1}" + Environment.NewLine + ") t) tab  WHERE tab.ROWNUMBER >= " + index + " and tab.ROWNUMBER < " + count;
		return string.Format(format, "rownum", sql);
	}

	protected override string GetRowNumUpdate(string tableName, string where, string column, string? rownumber)
	{
		return $"UPDATE ({"SELECT * FROM " + tableName + " " + where}) T1 SET {column} WHERE ROWNUM={rownumber}";
	}

	protected override string GetRowNumDelete(string tableName, string where, string? rownumber)
	{
		return $"DELETE FROM ({"SELECT * FROM " + tableName + " " + where}) T1 WHERE ROWNUM={rownumber}";
	}

	public DatabaseType GetConnectionStr(out string connectStr)
	{
		connectStr = "Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST={3})(PORT=1521)))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME={0})));User Id={1};Password={2};Pooling=true;Min Pool Size=0;Max Pool Size=100;Connection Timeout=60;Connection Lifetime=0;Persist Security Info=true ";
		connectStr = string.Format(connectStr, _connect.DataBase, _connect.UserID, _connect.PassWord, _connect.Server);
		return DatabaseType.Oracle;
	}
}
